/*=+--+=#=+--     Unmanned Aerial System Management Software      --+=#=+--+=#*\
|          Copyright (C) 2011 Regents of the University of Colorado.           |
|                             All Rights Reserved.                             |

     This program is free software: you can redistribute it and/or modify
     it under the terms of the GNU General Public License version 2 as
     published by the Free Software Foundation.

     This program is distributed in the hope that it will be useful,
     but WITHOUT ANY WARRANTY; without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     GNU General Public License for more details.

     You should have received a copy of the GNU General Public License
     along with this program.  If not, see <http://www.gnu.org/licenses/>.

            Jack Elston                       Cory Dixon                        
|           elstonj@colorado.edu              dixonc@colorado.edu              |
|                                                                              |
\*=+--+=#=+--                 --+=#=+--+=#=+--                    --+=#=+--+=#*/

/*!
  \file clientList.h
  \brief header file for XML parser

  \author Jack Elston
  $Date: 2006/10/25 13:34:45 $
  */

#ifndef __CLIENTLIST_H
#define __CLIENTLIST_H

#include <math.h>

#include "String.h"
#include "utilities.h"
#include "timeLib.h"
#include "commandStruct.h"
#include "capabilitiesManager.h"

/*<-------Defines--------->*/
#define MAX_CLIENTS 64
#define MAX_ADDRESSES 5
#define MAX_NUM_SONDE 2
/*<------End Defines------>*/

typedef struct _StateFlags {
	uint16_t init:1, timed_out:1, gps:1, gui:1, running:1, gs_backup:1, gs_telem:1, gs_wind:1,gs_fp:1,unused:8;
	void clear() {init=0;timed_out=0;gps=0;gui=0;running=0,gs_backup=0, gs_telem=0,gs_wind=0,gs_fp=0,unused=0;};
} StateFlags;

typedef struct _Client
{
	// client description
	String              name;
	in_addr             address[MAX_ADDRESSES];
	in_addr             bcast_addr[MAX_ADDRESSES];

	// client services
	uint8_t             stream_subscriptions[MAX_NUM_CAP];
	CapabilitiesManager capabilities;

	// client data
	Telemetry_t         telemetry;
	VehicleInfo_t       telemetry_client;
	LinkStatus_t        linkstatus[MAX_CLIENTS];
	Sonde_t             sonde[MAX_NUM_SONDE];
	CommStatus_t        comm[MAX_CLIENTS]; 
	AntPoint_t          antenna_pas;
	AntPoint_t          antenna_aps;
	WindData_t          wind;

  Mothership_t  mothership;

	// client health & status
	TimeStamp           last_rx;  // time of last received packet
	StateFlags          state;    // state of node, see commandStruct.h

	// initialize client struct
	_Client() {
		name = "";
		for(int j=0; j<MAX_NUM_SONDE; j++ ) {
			sonde[j].id = 255;
			sonde[j].pth.pressure = NAN;
			sonde[j].pth.temp     = NAN;
			sonde[j].pth.rh1      = NAN;
			sonde[j].pth.rh2      = NAN;
		}
		state.clear();
		for(int j=0; j<MAX_NUM_CAP; j++) {
			stream_subscriptions[j] = 0;
		}
		for(int j=0; j<MAX_ADDRESSES; j++) {
			address[j].s_addr    = INADDR_ANY;
			bcast_addr[j].s_addr = INADDR_ANY;
		}
		telemetry_client.id[0]=0;
	}

	// calculate range to another client
	float rangeTo(_Client * client) {
		if( !client ) return NAN;
		if( state.gps && client->state.gps )
			return GPSRange( telemetry.gps.pos, client->telemetry.gps.pos);
		else
			return NAN;
	}	
	
	// calculate range to another client
	float rangeTo(GPSLLA_t gps) {
		//if( state.gps )
			return GPSRange( telemetry.gps.pos, gps);
		//else
			//return NAN;
	}
} Client;

class ClientList
{
	private:
		int    num_clients;
		Client client_list[MAX_CLIENTS];
		float  range[MAX_CLIENTS];

		void clearAddresses(int client_num);

	public:
		ClientList();
		~ClientList() {}

		// Add client
		bool add(Client * a_client);
		bool add(String name);

		// Clear / Remove clients
		bool remove(Client * a_client);
		bool remove(String name);

		void clear();

		// Client access
		Client * getClient(int refnum);
		Client * getClient(String name);
		Client * getClient(in_addr addr);

		int getNumClients() {return num_clients;}
		int getRefNum(Client *);

		// Client addressing
		bool addAddr(Client * a_client, in_addr addr);
		bool addAddr(Client * a_client, in_addr addr, in_addr bcast);
		bool removeAddr(Client * a_client, in_addr addr);

		in_addr getAddr(Client * a_client);
		in_addr getAddr(Client * a_client, Client * dest_client);
		in_addr getBAddr(Client * a_client);

		// Client subscriptions
		Client * getSubscriptionsTo(uint8_t id, int last_client);
		bool isSubscribed(uint8_t id, int client);

		void subscribe(Client * a_client, uint8_t a_system);
		void unsubscribe(Client * a_client, uint8_t a_system);

		// User output
		void printList(void);

		// GPS Range functions 
		void  setRange(Client *);
		void  setRange(int refnum);
		float getRange(Client *);
		float getRange(int refnum);

};

#endif //define
